﻿using Furion.Localization;
using Furion;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using ST.Torch.WebApi.Core.Entities.System;
using Newtonsoft.Json.Linq;
using ST.Torch.WebApi.Application.System.Dtos;
using ST.Torch.WebApi.Core.Manager;
using ST.Torch.WebApi.Core.Manage.Cache;
using Microsoft.Extensions.Caching.Memory;

namespace ST.Torch.WebApi.Application.System.Services
{

    public class UIDService : IUIDService, IScoped
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private string _languageCulture;
        private IRepository _repository;
        private ICacheManage _cache;

        /// <summary>
        /// 过期时间
        /// </summary>
        private const int ExpirationTimeMinute = 60;
        public UIDService(IHttpContextAccessor httpContextAccessor
            , IRepository repository
            , ICacheManage memoryCache
            )
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = repository;
            _cache = memoryCache;
        }
        /// <summary>
        /// 语言
        /// </summary>
        public string languageCulture
        {
            get
            {
                if (!string.IsNullOrEmpty(_languageCulture))
                    return _languageCulture;
                if (!string.IsNullOrEmpty(L.GetSelectCulture().Culture.Name))
                    return L.GetSelectCulture().Culture.Name;
                string Lang = "zh-CN";
                L.SetCulture(Lang);
                return Lang;//默认中文
            }
            set
            {
                var culture = value != null ? value : null;
                _languageCulture = value;
            }
        }
        public Guid UserId
        {
            get
            {
           
                if (!string.IsNullOrEmpty(App.User?.FindFirstValue("UserId")))
                {
                    return Guid.Parse(App.User?.FindFirstValue("UserId"));

                }
                //JWT
                if (_httpContextAccessor.HttpContext?.Request.Headers["Authorization"].Count > 0)
                {
                    try
                    {
                        var jwtStr = _httpContextAccessor.HttpContext.Request.Headers["authorization"][0];
                        //var userToken = Furion.DataEncryption.JWTEncryption.ReadJwtToken(jwtStr.Replace("Bearer", "").Trim());
                        var userToken = Furion.DataEncryption.JWTEncryption.ReadJwtToken(jwtStr.Replace(JwtBearerDefaults.AuthenticationScheme, "").Trim());
                        if (userToken == null) return Guid.Empty;
                        var UserData = userToken.Claims.Where(u => u.Type == "UserId").ToList();
                        if (UserData.Count > 0)
                        {
                            foreach (var Claimitem in UserData)
                            {
                                if (Claimitem.Type == "UserId")
                                {
                                    Guid userId = Guid.Parse(Claimitem.Value);
                                  
                                    return userId;

                                }

                            }
                        }
                    }
                    catch (Exception ex)
                    {

                    }
                }
                return Guid.Empty;
            }
       
          
        }

        /// <summary>
        /// 用户
        /// </summary>
        public SYSUser User
        {
            get
            {
                string key = string.Format(CacheKeys.UIDService_User, UserId);
                if (!CacheKeys.UIDService_Users.Any(u => u == key))
                {
                    CacheKeys.UIDService_Users.Add(key);
                }
                var user = _cache.GetOrCreate(key, entity =>
                {
                    entity.SetAbsoluteExpiration(TimeSpan.FromMinutes(ExpirationTimeMinute));
                    entity.SetSlidingExpiration(TimeSpan.FromMinutes(ExpirationTimeMinute));
                    return _repository.Change<SYSUser>().FindOrDefault(UserId);
                });
                return user;

                // return _repository.Change<SYSUser>().FindOrDefault(UserId);

            }
        }
       

        /// <summary>
        /// 用户
        /// </summary>
        public SYSUserInfoDto UserInfo
        {
            get
            {
                string key = string.Format(CacheKeys.UIDService_UserInfo, UserId);
                if (!CacheKeys.UIDService_Users.Any(u => u == key))
                {
                    CacheKeys.UIDService_Users.Add(key);
                }
                var userInfo = _cache.GetOrCreate(string.Format(key, UserId), entity =>
                {
                    entity.SetAbsoluteExpiration(TimeSpan.FromMinutes(ExpirationTimeMinute));
                    entity.SetSlidingExpiration(TimeSpan.FromMinutes(ExpirationTimeMinute));
                    var UserRoleMenus = _repository.Change<SYSUser>().Include(u => u.Roles).ThenInclude(u => u.Menus).Single(u => u.Id == UserId);

                    SYSUserInfoDto UserData = UserRoleMenus.Adapt<SYSUserInfoDto>();
                    UserData.PermissionIds = UserRoleMenus.Roles.Select(u => u.Menus.Select(u => u.PermissionId)).ToList().SelectMany(u => u).ToList();
                    UserData.Roles = UserRoleMenus.Roles.Select(u => u.RoleCode).ToList();
                    var TempMenus = UserRoleMenus.Roles.Select(u => u.Menus).ToList();

                    List<SYSMenu> MenuDate = new List<SYSMenu>();

                    foreach (var menu in TempMenus)
                    {
                        MenuDate.AddRange(menu);
                    }
                    MenuDate = MenuDate.DistinctBy(u => u.Id).Where(u => !u.IsHide && (u.Type == MenuTypeEnum.Menu || u.Type == MenuTypeEnum.Page)).OrderBy(u => u.Sort).ToList();
                    if (UserRoleMenus.Account == "Administrator")
                    {
                        MenuDate = _repository.Change<SYSMenu>().Where(u => u.Type == MenuTypeEnum.Menu || u.Type == MenuTypeEnum.Page)
                        .Where(u=>u.IsHide!=true)
                        .OrderBy(u => u.Sort).ToList();
                        UserData.PermissionIds = _repository.Change<SYSMenu>().Where(u => !string.IsNullOrEmpty(u.PermissionId)).OrderBy(u => u.Sort).Select(u => u.PermissionId).ToList();
                    }
                    UserData.MenuIds = MenuDate.Select(u => u.Id).ToList();

                    UserData.UIMenus = GetTreeMenus(MenuDate, Guid.Empty);
                    return UserData;
                });

                return userInfo;
                //return UserData;
            }

        }
        private List<LayuiMenuDto> GetTreeMenus(List<SYSMenu> systemModules, Guid? pId)
        {
            List<LayuiMenuDto> MenuSecurities = new List<LayuiMenuDto>();
            foreach (var menu in systemModules.FindAll(r => r.ParentId == pId))
            {
                if (menu.Type == MenuTypeEnum.Menu || menu.Type == MenuTypeEnum.Page)
                {
                    var menuSecurity = menu.Adapt<LayuiMenuDto>();
                    menuSecurity.children = GetTreeMenus(systemModules, menu.Id);
					//menuSecurity.title =L.Text[menuSecurity.title];

                    MenuSecurities.Add(menuSecurity);
                }
            }
            return MenuSecurities;
        }

        /// <summary>
        /// 权限ID是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool IsExisePermissionId(string key)
        {
            if(UserInfo.PermissionIds.Any(u=>u==key)){
                return true;
            }
            return false;
        }
        public async Task CleanAllCache()
        {
            foreach (var item in CacheKeys.UIDService_Users)
            {
                await _cache.RemoveAsync(item);
            }
            CacheKeys.UIDService_Users.Clear();
        }
        public async Task CleanCache()
        {
            await  CleanCacheById(UserId);
        }
        public async Task CleanCacheById(Guid userId)
        {
            string userkey = string.Format(CacheKeys.UIDService_User, userId);
            string userInfokey = string.Format(CacheKeys.UIDService_UserInfo, userId);
            await _cache.RemoveAsync(userkey);
            await _cache.RemoveAsync(userInfokey);
            CacheKeys.UIDService_Users.Remove(userkey);
            CacheKeys.UIDService_Users.Remove(userInfokey);

        }
        

    }

}
